package SellerAgent;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.*;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.event.CellEditorListener;
import javax.swing.table.TableCellEditor;

import Ontologies.TreeWithPrice;

/**
 * Created with IntelliJ IDEA.
 * User: jiaka_000
 * Date: 13-5-11
 * Time: 11:11
 * this class define the view of seller's gui
 */
public class SellerGUI extends JFrame {
    public static final Integer DEFAULT_QUANTITY = 10;
    public static final int CONTROL_HEIGHT = 20;
    public static final int BUTTON_HEIGHT = 30;
    public static final int BORDER = 5;
    public static final int CONTROL_WIDTH = 80;
    public static final int WINDOW_WIDTH = 520;
    public static final int WINDOW_HEIGHT = 520;
    public static final int COLUMN_UNIT_PRICE = 3;
    public static final int COLUMN_QUANTITY = 4;

    /**
     * the reference of seller agent
     */
    private Seller myAgent;
    private final JTextField txtQuantity;

    /**
     * the map for all kind of tree, take category as key, a list of trees belong to that category as value
     */
    private Map<String, java.util.List<TreeWithPrice>> trees;
    private List<TreeWithPrice> sellingList;
    private JTextField txtUnitPrice;
    private JComboBox comboBoxTree;
    private JComboBox comboBoxCategory;
    private final JTable table;
    private final JButton addButton;
    private final JButton btnRemove;
    private final JButton btnSave;
    private final JButton btnStart;

    /**
     * the constructor of seller gui class
     * initialize seller gui
     * @param myAgent
     */
    public SellerGUI(Seller myAgent) {
        super(myAgent.getLocalName());
        this.myAgent = myAgent;

        //preparing all needed data for the following steps
        initializeTreesData();

        //define the position of all controls
        setTitle(myAgent.getLocalName());
        setResizable(false);
        //setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        //TODO DuyHanPhan 23May not allow user to close SellerGUI window
        this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

        setBounds(400, 200, WINDOW_WIDTH, WINDOW_HEIGHT);
        JPanel contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(BORDER, BORDER, BORDER, BORDER));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        // variables for controls' postions
        int row1Y = BORDER;
        int row2Y = BORDER * 2 + CONTROL_HEIGHT;
        int col1X = BORDER;
        int col2X = BORDER + CONTROL_WIDTH;
        int col3X = BORDER * 4 + CONTROL_WIDTH * 3;
        int col4X = BORDER * 5 + CONTROL_WIDTH * 4;

        JLabel lblCategory = new JLabel("Category");
        lblCategory.setBounds(col1X, row1Y, CONTROL_WIDTH, CONTROL_HEIGHT);
        contentPane.add(lblCategory);

        comboBoxCategory = new JComboBox();
        //comboBoxCategory.setMaximumRowCount(20);
        comboBoxCategory.setBounds(col2X, row1Y, CONTROL_WIDTH * 2, CONTROL_HEIGHT);
        contentPane.add(comboBoxCategory);

        JLabel lblTree = new JLabel("Tree");
        lblTree.setBounds(col3X, row1Y, CONTROL_WIDTH, CONTROL_HEIGHT);
        contentPane.add(lblTree);

        comboBoxTree = new JComboBox();
        comboBoxTree.setBounds(col4X, row1Y, CONTROL_WIDTH * 2, CONTROL_HEIGHT);
        contentPane.add(comboBoxTree);


        JLabel label = new JLabel("Unit Price:");
        label.setBounds(col1X, row2Y, CONTROL_WIDTH, CONTROL_HEIGHT);
        contentPane.add(label);
        txtUnitPrice = new JTextField();
        txtUnitPrice.setBounds(col2X, row2Y, CONTROL_WIDTH, CONTROL_HEIGHT);
        contentPane.add(txtUnitPrice);

        JLabel lblQuantity = new JLabel("Quantity");
        lblQuantity.setBounds(col3X, row2Y, CONTROL_WIDTH, CONTROL_HEIGHT);
        contentPane.add(lblQuantity);

        txtQuantity = new JTextField();
        txtQuantity.setBounds(col4X, row2Y, CONTROL_WIDTH, CONTROL_HEIGHT);
        txtQuantity.setText(DEFAULT_QUANTITY.toString());
        contentPane.add(txtQuantity);

        addButton = new JButton("AddToSellingList");
        addButton.setBounds(col4X, txtQuantity.getY() + txtQuantity.getHeight() + BORDER, CONTROL_WIDTH * 2, BUTTON_HEIGHT);
        contentPane.add(addButton);

        JSeparator separator = new JSeparator();
        separator.setBounds(0, addButton.getY() + addButton.getHeight() + BORDER, getWidth(), CONTROL_HEIGHT / 2);
        contentPane.add(separator);

        JLabel lblSellingList = new JLabel("Selling List:");
        lblSellingList.setBounds(col1X, separator.getY() + separator.getHeight(), CONTROL_WIDTH, CONTROL_HEIGHT);
        contentPane.add(lblSellingList);

        table = new JTable(new SellingListTableModel(sellingList)){

            public boolean isCellEditable(int row, int column) {
                return column == COLUMN_UNIT_PRICE || column == COLUMN_QUANTITY; //only the column of price and quantity can be edited

            }};
        table.putClientProperty("terminateEditOnFocusLost", true);
        int tableY = lblSellingList.getY() + lblSellingList.getHeight() + BORDER;
        int tableW = WINDOW_WIDTH - 3 * BORDER;
        int tableH = 320;
        //table.setBounds(col1X, tableY, tableW, tableH);
        //table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        //contentPane.add(table.getTableHeader());
        JScrollPane scrollPane= new JScrollPane(table);//put the table into a scrollable pane
        scrollPane.setBounds(col1X, tableY, tableW, tableH);
        contentPane.add(scrollPane);

        btnRemove = new JButton("Remove");
        btnRemove.setBounds(getWidth() / 5, tableY + tableH + BORDER, CONTROL_WIDTH, BUTTON_HEIGHT);
        contentPane.add(btnRemove);

        btnSave = new JButton("Save");
        btnSave.setBounds(getWidth() * 2 / 5, tableY + tableH + BORDER, CONTROL_WIDTH, BUTTON_HEIGHT);
        contentPane.add(btnSave);

        btnStart = new JButton("Start");
        btnStart.setBounds(getWidth() * 3 / 5, tableY + tableH + BORDER, CONTROL_WIDTH, BUTTON_HEIGHT);
        contentPane.add(btnStart);

        // fill initial data into controls
        initializeGUIData();
        // set controls' event
        initializeEvents();
    }

    /**
     * this method set controls default value
     */
    private void initializeGUIData() {

        for (String string : trees.keySet()) {
            comboBoxCategory.addItem(string);
        }

        //if the selling list has trees, change the selected category,and disable the category comboBox
        if(sellingList.size()!=0)
        {
            comboBoxCategory.setSelectedItem(sellingList.get(0).getCategory());
            comboBoxCategory.setEnabled(false);
        }

        for (TreeWithPrice tree :trees.get((String)comboBoxCategory.getSelectedItem())) {
            comboBoxTree.addItem(tree.getCommonName());
        }

        if (trees.get(comboBoxCategory.getSelectedItem()).size() != 0) {
            Float price = trees.get((String)comboBoxCategory.getSelectedItem()).get(0).getUnitPrice();
            txtUnitPrice.setText(price.toString());
        } else {
            txtUnitPrice.setText("0.00");
        }
    }

    /**
     * this event set all necessary evernt handler
     */
    private void initializeEvents() {
        comboBoxCategory.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    // when choose another category, refresh the tree combo box
                    comboBoxTree.removeAllItems();
                    for (TreeWithPrice tree : trees.get((String)comboBoxCategory.getSelectedItem())) {
                        comboBoxTree.addItem(tree.getCommonName());
                    }
                }
            }
        });

        comboBoxTree.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    for (TreeWithPrice tree : trees.get((String)comboBoxCategory.getSelectedItem())) {
                        if (tree.getCommonName().equals(comboBoxTree.getSelectedItem())) {
                            Float price = trees.get((String)comboBoxCategory.getSelectedItem()).get(0).getUnitPrice();
                            txtUnitPrice.setText(price.toString());
                            break;
                        }
                    }
                }
            }
        });

        addButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {

                float price = Float.parseFloat(txtUnitPrice.getText());
                int quantity= Integer.parseInt(txtQuantity.getText());
                if(price <=0)
                {
                    showMessageBox("Unit Price cannot be negative number");
                    return;
                }
                else if(quantity <= 0)
                {
                    showMessageBox("Quantity cannot be negative number");
                    return;
                }

                for (TreeWithPrice tree : trees.get((String) comboBoxCategory.getSelectedItem())) {
                    if (tree.getCommonName().equals(comboBoxTree.getSelectedItem())) {
                        if(!sellingList.contains(tree))
                        {

                        TreeWithPrice newTree = new TreeWithPrice(tree);
                        newTree.setUnitPrice(price);
                        newTree.setQuantity(quantity);
                        sellingList.add(newTree);
                        SellingListTableModel tableModel= (SellingListTableModel)table.getModel();
                        tableModel.addRow(newTree);

                        table.updateUI();

                        //if the table is in editing, retrieve from editing mode
                        if(table.isEditing()){
                            int row = table.getEditingRow();
                            int col = table.getEditingColumn();
                            table.getCellEditor(row,col).stopCellEditing();
                        }

                        //once the selling list has trees, user cannot change the category
                        comboBoxCategory.setEnabled(false);
                        }
                        else
                        {
                            showMessageBox("Sorry, this tree already in selling list");
                        }
                        break;
                    }
                }

            }
        });

        btnRemove.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                SellingListTableModel tableModel= (SellingListTableModel)table.getModel();
                sellingList.remove(table.getSelectedRow());
                tableModel.removeRow(table.getSelectedRow());
                table.updateUI();

                if(sellingList.size()==0)
                {
                    //if the selling list is empty, enable the category box to allow user to change category
                    comboBoxCategory.setEnabled(true);
                }

            }
        });

        btnSave.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                myAgent.saveSellingListToFile(sellingList);
                showMessageBox("The sellingList is saved");
            }
        });

        btnStart.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                //save the selling list and start selling
                if(sellingList.size()>0)
                {
                myAgent.saveSellingListToFile(sellingList);
                myAgent.StartSelling();
                myAgent.updateGUI();
                showMessageBox("The seller agent starts selling");
                }
                else
                {
                    showMessageBox("Sorry, there is no trees in selling list");
                }
            }
        });
    }

    private void showMessageBox(String msg)
    {
        JOptionPane.showConfirmDialog(
                this, msg, "Notice",JOptionPane.DEFAULT_OPTION);
    }


    /**
     * initialize tree data
     * basically, this method generate a map <Category, treeList>
     *     each category match along with a list of trees belong to that category
     */
    private void initializeTreesData() {
        trees = new HashMap<String, List<TreeWithPrice>>();
        if (myAgent instanceof Seller) {
            for (TreeWithPrice tree : ((Seller) myAgent).getAllTreesList()) {
                String category = tree.getCategory();
                if (trees.containsKey(category)) {
                    trees.get(category).add(tree);
                } else {
                    List<TreeWithPrice> list = new ArrayList<TreeWithPrice>();
                    list.add(tree);
                    trees.put(category, list);
                }
            }

            sellingList= new ArrayList<TreeWithPrice>(((Seller) myAgent).getSellingList());
        }

    }

    public void showGui() {
//        pack();
//        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
//        int centerX = (int)screenSize.getWidth() / 2;
//        int centerY = (int)screenSize.getHeight() / 2;
//        setLocation(centerX - getWidth() / 2, centerY - getHeight() / 2);
        super.setVisible(true);
    }
}
